Visualización de datos con Python

Autor: Roberto Muñoz
Cargo: Data Scientist en MetricArts
Github: https://github.com/rpmunoz

Python es un lenguaje de programación abierto que fue creado por Guido van Rossum el año 1991. Python es uno de los lenguajes más empleados por la comunidad de Data Science en el mundo y cuenta con un gran número de librerías para procesar, analizar y visualizar datos.

Para visualizar datos en Python debemos cargar algunas librerías. Las librerías más empleadas para analizar y visualizar datos son las siguientes,

  • numpy: Numpy es una librería de Python usada para cálculo numérico y científico. Abreviatura de Numerical Python.
  • pandas: Pandas es una librería de Python usada para el análisis de datos. Ofrece estructuras de datos flexibles y permite trabajar con ellos de forma muy eficiente.
  • matplotlib: Matplotlib es la librería más popular de Python para hacer visualizaciones y gráficos. Matplotlib posee gran flexibilidad para generar diferentes tipos de gráficos.
  • seaborn: Seaborn es una librería de visualización basada en matplotlib. La idea de Seaborn es que los científicos de datos dispongan de una interfaz para hacer gráficos estadísticos atractivos e explicativos.

In [1]:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

%matplotlib inline
params = {'legend.fontsize': 'x-large',
          'figure.figsize': (10, 7.5),
         'axes.labelsize': 'x-large',
         'axes.titlesize':'x-large',
         'xtick.labelsize':'x-large',
         'ytick.labelsize':'x-large'}
plt.rcParams.update(params)

Lectura de datos

Para este tutorial usaremos una base de datos de vuelos áreos publicada por el sitio web Openflights. La base de datos contiene una tabla de los aeropuertos en el mundo (aeropuertos.csv), una tabla de las aerolíneas en el mundo (aerolineas.csv) y una tabla de las rutas de vuelos comerciales (rutas.csv).

Más información en https://github.com/jpatokal/openflights


In [2]:
aeropuertos_file='data/aeropuertos.csv'
aerolineas_file='data/aerolineas.csv'
rutas_file='data/rutas.csv'

aeropuertos=pd.read_csv(aeropuertos_file)
aerolineas=pd.read_csv(aerolineas_file)
rutas=pd.read_csv(rutas_file)

In [3]:
aeropuertos.head()


Out[3]:
Id Nombre Ciudad Pais IATA OACI Latitud Longitud Altitud Zona_horaria Horario_verano Zona_horaria_lugar Tipo Fuente
0 1 Goroka Airport Goroka Papua New Guinea GKA AYGA -6.081690 145.391998 1610.0 10.0 U Pacific/Port_Moresby airport OurAirports
1 2 Madang Airport Madang Papua New Guinea MAG AYMD -5.207080 145.789001 6.1 10.0 U Pacific/Port_Moresby airport OurAirports
2 3 Mount Hagen Kagamuga Airport Mount Hagen Papua New Guinea HGU AYMH -5.826790 144.296005 1642.3 10.0 U Pacific/Port_Moresby airport OurAirports
3 4 Nadzab Airport Nadzab Papua New Guinea LAE AYNZ -6.569803 146.725977 72.8 10.0 U Pacific/Port_Moresby airport OurAirports
4 5 Port Moresby Jacksons International Airport Port Moresby Papua New Guinea POM AYPY -9.443380 147.220001 44.5 10.0 U Pacific/Port_Moresby airport OurAirports

In [4]:
aerolineas.head()


Out[4]:
Linea_aerea_Id Linea_aerea Alias IATA OACI Sigla_identificacion Pais Activa
0 -1 Unknown NaN - NaN NaN NaN Y
1 1 Private flight NaN - NaN NaN NaN Y
2 2 135 Airways NaN NaN GNL GENERAL United States N
3 3 1Time Airline NaN 1T RNX NEXTIME South Africa Y
4 4 2 Sqn No 1 Elementary Flying Training School NaN NaN WYT NaN United Kingdom N

In [5]:
rutas.head()


Out[5]:
Linea_aerea Linea_aerea_Id Aeropuerto_origen Aeropuerto_origen_Id Aeropuerto_destino Aeropuerto_destino_Id Vuelo_operado Numero_paradas Modelo_avion Pais_origen Pais_destino Distancia_km
0 2B 410 AER 2965 KZN 2990 NaN 0 CR2 Russia Russia 1505.879589
1 2B 410 ASF 2966 KZN 2990 NaN 0 CR2 Russia Russia 1039.785086
2 2B 410 ASF 2966 MRV 2962 NaN 0 CR2 Russia Russia 447.883531
3 2B 410 CEK 2968 KZN 2990 NaN 0 CR2 Russia Russia 770.024740
4 2B 410 CEK 2968 OVB 4078 NaN 0 CR2 Russia Russia 1337.791014

Visualización de datos

1. Histograma de frecuencia absoluta

Uno de los gráficos más usados para la visualización de datos es el histograma. Un histograma es una representación gráfica de una variable en forma de barras, donde la superficie de cada barra es proporcional a la frecuencia de los valores representados. Sirven para obtener una primera vista general de la distribución de la muestra de datos respecto a una característica.

Supongamos que nos interesa contar el número de vuelos de acuerdo a la distancia recorrida en kilómetros. Para ello construimos un histograma de la Distancia de los vuelos.


In [6]:
n, bins, patches = plt.hist(rutas['Distancia_km'], bins=20)
plt.xlabel('Distancia recorrida (km)')
plt.ylabel('Número de vuelos')
plt.title('Histograma - Frecuencia absoluta')


Out[6]:
<matplotlib.text.Text at 0x1fe50e36588>

Es importante notar que los histogramas se contruyen usando variables cuantitativas, como es el caso de la variable Distancia recorrida (km).

2. Histograma de frecuencia relativa


In [7]:
sns.distplot(rutas['Distancia_km'], bins=20)
plt.xlabel('Distancia recorrida (km)')
plt.ylabel('Número de vuelos')
plt.title('Histograma - Frecuencia relativa')


Out[7]:
<matplotlib.text.Text at 0x1fe512752e8>

3. Gráfico de barras

Otro gráfico ampliamente usado es el diagrama de barras o gráfico de barras. Es una representación gráfica de un conjunto de datos o valores, y está conformado por barras rectangulares de longitudes proporcionales a los valores representados.

A diferencia de un histograma, el gráfico de barras se construye usando variables categóricas o cualitativas.

Digamos que nos interesa separar los vuelos en cortos, intermedios y largos de acuerdo a la distancia recorrida. Para ello, creamos tres categorías y hacemos un gráfico de barras.


In [8]:
bins = [0, 2000, 10000, 1000000]
group_names = ['Vuelo corto', 'Vuelo intermedio', 'Vuelo largo']
rutas['Tipo_vuelo'] = pd.cut(rutas['Distancia_km'], bins, labels=group_names)

In [9]:
sns.countplot(x="Tipo_vuelo", order=group_names, data=rutas)
plt.xlabel('Tipo de vuelo')
plt.ylabel('Número de vuelos')
plt.title('Gráfico de barras')
plt.xticks(size = 15, rotation=60)


Out[9]:
(array([0, 1, 2]), <a list of 3 Text xticklabel objects>)

Digamos que nos interesa conocer el número de vuelos que parten desde algún país en Sudamérica. La mejor manera de visualizar el número de vuelos por país es usando un gráfico de barras.


In [10]:
paises_sudamerica=['Brazil','Colombia','Argentina','Peru','Venezuela','Chile','Ecuador','Bolivia','Paraguay','Uruguay','Guyana','Suriname','French Guiana']
rutas_sudamerica=rutas[rutas['Pais_origen'].isin(paises_sudamerica)]
rutas_sudamerica_pais=rutas_sudamerica.groupby('Pais_origen')['Linea_aerea'].agg('count').sort_values(ascending=False)

In [11]:
sns.countplot(x="Pais_origen", order=rutas_sudamerica_pais.index.tolist(), data=rutas_sudamerica)
plt.xlabel('País de origen')
plt.ylabel('Número de vuelos')
plt.title('Gráfico de barras')
plt.xticks(size = 15, rotation=60)


Out[11]:
(array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12]),
 <a list of 13 Text xticklabel objects>)

4. Gráfico de cajas

Otro gráfico usado es el diagrama de caja o gráfico de caja. Es un gráfico que está basado en cuartiles y mediante el cual se visualiza la distribución de un conjunto de datos. Está compuesto por un rectángulo (caja) y dos brazos (bigotes).

Digamos que nos interesa conocer cómo se distribuyen los vuelos en cada país de Sudamérica. Para ello usamos la variable País de origen como variable categórica y la variable Distancia recorrida para estudiar su distribución.


In [13]:
sns.boxplot(x='Pais_origen', y='Distancia_km', order=rutas_sudamerica_pais.index.tolist(), data=rutas_sudamerica)
plt.xlabel('País de origen')
plt.ylabel('Distancia recorrida (km)')
plt.title('Gráfico de cajas')
plt.xticks(size = 15, rotation=60)


Out[13]:
(array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12]),
 <a list of 13 Text xticklabel objects>)

4. Gráfico de puntos

Otro gráfico usado es el diagrama de dispersión o gráfico de puntos. Es un gráfico que utiliza las coordenadas cartesianas para mostrar los valores de dos variables de un conjunto de datos.

Cabe notar que un gráfico de puntos se construye usando variables cuantitativas.

Supongamos que nos interesa saber si los vuelos que parten desde el hemisferio Norte son más largos que los vuelos que parten desde el hemisferio Sur. Para ello usamos la variable Latitud País de origen como variable dependiente y la variable Distancia recorrida como variable independiente.


In [16]:
rutas_coordenadas=rutas.merge(aeropuertos[['Id','Latitud','Longitud']], how='inner', left_on='Aeropuerto_origen_Id', right_on='Id')
rutas_coordenadas=rutas_coordenadas.sample(10000)

In [17]:
rutas_coordenadas.plot.scatter(x='Latitud', y='Distancia_km', s=3);
plt.xlim(-90,90)
plt.xlabel('Latitud País de origen')
plt.ylabel('Distancia recorrida (km)')
plt.title('Gráfico de puntos - Vuelos')
plt.xticks(size = 15, rotation=0);


Digamos que nos interesa saber como están distribuidos los aeropuertos en el mundo. Para ello usamos las variables Longitud y Latitud de la tabla aeropuertos.


In [18]:
aeropuertos.plot.scatter(x='Longitud', y='Latitud', s=3);
plt.xlim(-180,180)
plt.ylim(-90,90)
plt.xlabel('Longitud')
plt.ylabel('Latitud')
plt.title('Gráfico de puntos - Aeropuertos')
plt.xticks(size = 15, rotation=0);


Gracias por su atención


In [ ]:


In [ ]:


In [ ]:


In [ ]:

Preparación de datasets


In [ ]:
aeropuertos_file='data/airports.dat'
aeropuertos=pd.read_csv(aeropuertos_file, header=None)

aeropuertos.head()

In [ ]:
columnas=['Id','Nombre','Ciudad','Pais','IATA','OACI','Latitud','Longitud','Altitud','Zona_horaria','Horario_verano','Zona_horaria_lugar','Tipo','Fuente']
aeropuertos.columns = columnas
aeropuertos = aeropuertos.replace("\\N", value=np.nan)
aeropuertos['Altitud']=np.round(aeropuertos['Altitud']*0.3048,1)
aeropuertos[['Zona_horaria','Altitud']] = aeropuertos[['Zona_horaria','Altitud']].apply(pd.to_numeric)
aeropuertos.head()

In [ ]:
aeropuertos.dtypes

In [ ]:
aeropuertos.to_csv('data/aeropuertos.csv', index=False)

In [ ]:


In [ ]:
rutas_file='data/routes.dat'
rutas=pd.read_csv(rutas_file, header=None)

rutas.head()

In [ ]:
columnas=['Linea_aerea','Linea_aerea_Id','Aeropuerto_origen','Aeropuerto_origen_Id','Aeropuerto_destino','Aeropuerto_destino_Id','Vuelo_operado','Numero_paradas','Modelo_avion']
rutas.columns = columnas
rutas = rutas[(rutas["Linea_aerea_Id"] != "\\N") & (rutas["Aeropuerto_origen_Id"] != "\\N") & (rutas["Aeropuerto_destino_Id"] != "\\N")]
rutas[['Linea_aerea_Id','Aeropuerto_origen_Id','Aeropuerto_destino_Id']] = rutas[['Linea_aerea_Id','Aeropuerto_origen_Id','Aeropuerto_destino_Id']].apply(pd.to_numeric)
rutas.head()

In [ ]:
rutas.dtypes

In [ ]:
def pais_aeropuerto(row, name):
    result='Unknown'
    try:
        result = aeropuertos[aeropuertos["Id"] == row[name]].iloc[0]
        result = result['Pais']
    except (ValueError, IndexError):
        pass
    return result

In [ ]:
rutas['Pais_origen']=rutas.apply(pais_aeropuerto, name='Aeropuerto_origen_Id', axis=1)
rutas['Pais_destino']=rutas.apply(pais_aeropuerto, name='Aeropuerto_destino_Id', axis=1)

In [ ]:
import math

def haversine(lon1, lat1, lon2, lat2):
    # Convert coordinates to floats.
    lon1, lat1, lon2, lat2 = [float(lon1), float(lat1), float(lon2), float(lat2)]
    # Convert to radians from degrees.
    lon1, lat1, lon2, lat2 = map(math.radians, [lon1, lat1, lon2, lat2])
    # Compute distance.
    dlon = lon2 - lon1 
    dlat = lat2 - lat1 
    a = math.sin(dlat/2)**2 + math.cos(lat1) * math.cos(lat2) * math.sin(dlon/2)**2
    c = 2 * math.asin(math.sqrt(a)) 
    km = 6367 * c
    return km

def calcular_distancia(row):
    dist = 0
    try:
        # Match source and destination to get coordinates.
        source = aeropuertos[aeropuertos["Id"] == row["Aeropuerto_origen_Id"]].iloc[0]
        dest = aeropuertos[aeropuertos["Id"] == row["Aeropuerto_destino_Id"]].iloc[0]
        # Use coordinates to compute distance.
        dist = haversine(dest["Longitud"], dest["Latitud"], source["Longitud"], source["Latitud"])
    except (ValueError, IndexError):
        pass
    return dist

In [ ]:
rutas['Distancia_km'] = rutas.apply(calcular_distancia, axis=1)

In [ ]:
rutas.to_csv('data/rutas.csv', index=False)

In [ ]:


In [ ]:
aerolineas_file='data/airlines.dat'
aerolineas=pd.read_csv(aerolineas_file, header=None)

aerolineas.head()

In [ ]:
columnas=['Linea_aerea_Id','Linea_aerea','Alias','IATA','OACI','Sigla_identificacion','Pais','Activa']
aerolineas.columns = columnas
aerolineas = aerolineas.replace("\\N", value=np.nan)
aerolineas['Linea_aerea_Id'] = aerolineas['Linea_aerea_Id'].apply(pd.to_numeric)
aerolineas.head()

In [ ]:
aerolineas.dtypes

In [ ]:
aerolineas.to_csv('data/aerolineas.csv', index=False)

In [ ]:

Gráficos extras


In [ ]:
rutas['Largo_km'].plot.hist(alpha=0.5, bins=20)